package optiondef

import (
	"fmt"
	"photowall/pkg/log"
	"strings"
	"sync"
)

type UserService struct {
	WxUserRegisterLoginService
	AlbumService
}

// wx登录综合信息结构体
type WxRegisterLoginInfo struct {
	Jscode   string
	ID       string
	Password string
	Session  string
	OpenID   string
	loginRequestRes
}

type WxUserRegisterLoginService interface {
	WxRegisterUser(info *WxUserInfo) (bool, error)
	WxLoginUser(info *WxRegisterLoginInfo) (string, error)
	WxLogoutUser(info *WxRegisterLoginInfo) (bool, error)
	WxDeleteUser(info *WxUserInfo) (bool, error)
	WxIsUserLogged(info *WxRegisterLoginInfo) (bool, error)
	WxGetUserinfo(info *WxRegisterLoginInfo) (*WxUserInfo, error)
}

var (
	userServiceInstan         *UserService
	userServiceInstanSyncOnce sync.Once
)

func GetWxUserService() WxUserRegisterLoginService {
	userServiceInstanSyncOnce.Do(func() {
		userServiceInstan = &UserService{}
	})

	return userServiceInstan
}

func (userService *UserService) WxRegisterUser(info *WxUserInfo) (bool, error) {
	if len(strings.TrimSpace(info.OpenID)) == 0 || len(strings.TrimSpace(info.ID)) == 0 {
		log.GetDatabaseLogger().Info(fmt.Sprintf(`func WxRegisterUser receive null info struct, %v,
		 openid is %v, id is %v ,union_id is %v`, *info, info.OpenID, info.ID, info.UnionID))
		return false, fmt.Errorf(`func WxRegisterUser receive info have no needed fields, %v`, *info)
	}

	// 确认是否在数据库， 这一个步骤是否多余了，直接让它抛出错误好了？
	userinfo, err := getWxUserdbService().GetWxUserInDb(&WxUserInfo{OpenID: info.OpenID})
	if err != nil {
		return false, err
	}

	if userinfo != nil {
		return true, nil
	}

	res, err := getWxUserdbService().AddWxUserToDb(info)
	if err != nil {
		log.GetDatabaseLogger().Error(fmt.Sprintf("func WxRegisterUser:cat not add user %v ", err))
		return false, err
	}

	return res, nil
}

func (userService *UserService) WxLoginUser(info *WxRegisterLoginInfo) (string, error) {
	session, err := wechatLogin(info.Jscode)
	if err != nil {
		return "", err
	}

	return session, nil
}

func (userService *UserService) WxLogoutUser(info *WxRegisterLoginInfo) (bool, error) {
	return logoutWechatUserBysessionInRedis(info.Session)
}

func (userService *UserService) WxIsUserLogged(info *WxRegisterLoginInfo) (bool, error) {
	res, err := checkWxUserIsLoggedByRedis(info.Session)

	if res {
		go func() {
			_, err := refreashWxUserLogginExpiretimeBySessionImRedis(info.Session)
			if err != nil {
				log.GetRedisLogger().Info(`func refreashWxUserLogginExpiretimeBySessionImRedis act failed` + err.Error())
			}
		}()
	}

	return res, err
}

func (userService *UserService) WxDeleteUser(info *WxUserInfo) (bool, error) {
	if len(strings.TrimSpace(info.OpenID)) == 0 {
		return false, fmt.Errorf(`can not delete null openid, %v`, *info)
	}

	getWxUserdbService().DeleteWxUserInDb(&WxUserInfo{OpenID: info.OpenID})
	return false, nil
}

func (userService *UserService) WxGetUserinfo(info *WxRegisterLoginInfo) (*WxUserInfo, error) {
	openID, err := getWxUserOpenIDBySessionInRedis(info.Session)
	if err != nil {
		log.GetMainLogger().Error(fmt.Sprintf(`get openid by session in redis failed, %v`, *info))
		return nil, err
	}

	res, err := getWxUserdbService().GetWxUserInDb(&WxUserInfo{OpenID: openID})
	if err != nil {
		log.GetMainLogger().Error(fmt.Sprintf(`can not find user in db,%v`, *info))
		return nil, err
	}

	return res, nil
}
